home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlb20 / lib / _normdf.cpp < prev    next >
C/C++ Source or Header  |  1992-03-30  |  5KB  |  208 lines

  1. | mjr: not needed _normdf for -__M68881__ or the sfp004
  2. | however, _infinitydf is retained
  3.  
  4. |#######################################################################
  5.  
  6. | double floating point normalization routine
  7. |
  8. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  9. | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
  10. |
  11. | Revision 1.6, kub 04-90 :
  12. | more robust handling exponent and sign handling for 32 bit integers. There
  13. | are now overflow tests for 32 bit exponents, and bit 31 of the sign flag
  14. | is or ed to bit 15 for later checks (i.e. both bits 31 and 15 are now sign
  15. | bits). Take care, the upper 16 bits of rounding info are ignored for 32 bit
  16. | integers !
  17. |
  18. | Revision 1.5, ++jrb 03-90:
  19. | change __normdf interface to expect ints instead of shorts. easier
  20. | to interface to 32 bit int code. this file is now pre-processed,
  21. | with __MSHORT__ defined when ints are 16 bits.
  22. |
  23. | Revision 1.4, kub 03-90 :
  24. | export ___normdf entry to C language. Rename the internal entry to a name
  25. | not accessible from C to prevent crashes
  26. |
  27. | Revision 1.3, kub 01-90 :
  28. | added support for denormalized numbers
  29. |
  30. | Revision 1.2, kub 01-90 :
  31. | replace far shifts by swaps to gain speed
  32. |
  33. | Revision 1.1, kub 12-89 :
  34. | Ported over to 68k assembler
  35. |
  36. | Revision 1.0:
  37. | original 8088 code from P.S.Housel
  38.  
  39.     .text
  40.     .even
  41.     .globl    __infinitydf
  42.  
  43. #if !defined (__M68881__) && !defined (sfp004)
  44.     .globl    ___normdf
  45.     .globl    norm_df
  46.  
  47. # ifdef    ERROR_CHECK
  48. LC0:
  49.     .ascii "normdf: OVERFLOW\12\15\0"
  50.     .even
  51. # endif    ERROR_CHECK
  52.  
  53.     | C entry, for procs dealing with the internal representation :
  54.     | double __normdf(long long mant, int exp, int sign, int rbits);
  55. ___normdf:
  56.     lea    sp@(4),a0    | parameter pointer
  57.     moveml    d2-d7,sp@-    | save working registers
  58.     moveml    a0@+,d4-d5    | get mantissa
  59.  
  60. # ifdef __MSHORT__
  61.     movew    a0@+,d0        | get exponent
  62.     movew    a0@+,d2        | get sign
  63.     movew    a0@+,d1        | rounding information
  64. # else
  65.     movel    a0@+,d0        | get exponent
  66.     movel    a0@+,d2        | get sign
  67.     bpl    0f        | or bit 31 to bit 15 for later tests
  68.     orw    #0x8000,d2
  69. 0:    movel    a0@+,d1        | rounding information
  70.  
  71.     cmpl    #0x7fff,d0    | test exponent
  72.     bgt    oflow
  73.     cmpl    #-0x8000,d0
  74.     blt    retz
  75. # endif
  76.  
  77.     | internal entry for floating point package, saves time
  78.     | d0=u.exp, d2=u.sign, d1=rounding bits, d4/d5=mantissa
  79.     | registers d2-d7 must be saved on the stack !
  80. norm_df:
  81.     movel    d4,d3        | rounding and u.mant == 0 ?
  82.     orl    d5,d3
  83.     bne    1f
  84.     tstb    d1
  85.     beq    retz
  86. 1:
  87.     movel    d4,d3
  88.     andl    #0xfffff000,d3    | fast shift, 16 bits ?
  89.     bne    2f
  90.     cmpw    #9,d0        | shift is going to far; do normal shift
  91.     ble    2f        |  (minimize shifts here : 10l = 16l + 6r)
  92.     swap    d4        | yes, swap register halfs
  93.     swap    d5
  94.     movew    d5,d4
  95.     moveb    d1,d5        | some doubt about this one !
  96.     lslw    #8,d5
  97.     clrw    d1
  98.     subw    #16,d0        | account for swap
  99.     bra    1b
  100. 2:
  101.     clrb    d2        | sticky byte
  102.     movel    #0xffe00000,d6
  103. 3:    tstw    d0        | divide (shift)
  104.     ble    0f        |  denormalized number
  105.     movel    d4,d3
  106.     andl    d6,d3        |  or until no bits above 53
  107.     beq    4f
  108. 0:    addw    #1,d0        | increment exponent
  109.     lsrl    #1,d4
  110.     roxrl    #1,d5
  111.     orb    d1,d2        | set sticky
  112.     roxrb    #1,d1        | shift into rounding bits
  113.     bra    3b
  114. 4:
  115.     andb    #1,d2
  116.     orb    d2,d1        | make least sig bit sticky
  117.     movel    #0xfff00000,d6
  118. 5:    movel    d4,d3        | multiply (shift) until
  119.     andl    d6,d3        | one in implied position
  120.     bne    6f
  121.     subw    #1,d0        | decrement exponent
  122.     beq    6f        |  too small. store as denormalized number
  123.     addb    d1,d1        | some doubt about this one *
  124.     addxl    d5,d5
  125.     addxl    d4,d4
  126.     bra    5b
  127. 6:
  128.     tstb    d1        | check rounding bits
  129.     bge    8f        | round down - no action neccessary
  130.     negb    d1
  131.     bvc    7f        | round up
  132.     bclr    #0,d5        | tie case - round to even
  133.     bra    8f
  134. 7:
  135.     clrl    d1        | zero rounding bits
  136.     addl    #1,d5
  137.     addxl    d1,d4
  138.     tstw    d0
  139.     bne    0f        | renormalize if number was denormalized
  140.     addw    #1,d0        | correct exponent for denormalized numbers
  141.     bra    2b
  142. 0:    movel    d4,d3        | check for rounding overflow
  143.     andl    #0xffe00000,d3
  144.     bne    2b        | go back and renormalize
  145. 8:
  146.     movel    d4,d3        | check if normalization caused an underflow
  147.     orl    d5,d3
  148.     beq    retz
  149.     cmpw    #0,d0        | check for exponent overflow or underflow
  150.     blt    retz
  151.     cmpw    #2047,d0
  152.     bge    oflow
  153.  
  154.     lslw    #4,d0        | re-position exponent
  155.     andw    #0x8000,d2    | sign bit
  156.     orw    d2,d0
  157.     swap    d0        | map to upper word
  158.     clrw    d0
  159.     andl    #0x0fffff,d4    | top mantissa bits
  160.     orl    d0,d4        | insert exponent and sign
  161.     movel    d4,d0
  162.     movel    d5,d1
  163.     moveml    sp@+,d2-d7
  164.     rts
  165.  
  166.     .globl    _errno        | from <errno.h>
  167. ERANGE    =    63
  168.  
  169. retz:
  170. # ifdef __MSHORT__
  171.     movew    #ERANGE,_errno    | set errno
  172. # else
  173.     movel    #ERANGE,_errno    | set errno
  174. # endif
  175.     clrl    d0        | return zero value
  176.     clrl    d1
  177.     moveml    sp@+,d2-d7
  178.     rts
  179.  
  180. oflow:
  181.  
  182. #ifdef    ERROR_CHECK
  183.     moveml    d0-d1,a7@-
  184.     pea    LC0
  185.     pea    __iob+52    |
  186.     jbsr    _fprintf    |
  187.     addql    #8,a7        |
  188.     moveml    a7@+,d0-d1
  189. # ifdef __MSHORT__
  190.     movew    #ERANGE,_errno    | set errno
  191. # else
  192.     movel    #ERANGE,_errno    | set errno
  193. # endif
  194. #endif    ERROR_CHECK
  195.  
  196.     moveml    __infinitydf,d0-d1 | return infinty value
  197.     andw    #0x8000,d2    | get sign bit of argument
  198.     swap    d2
  199.     clrw    d2
  200.     orl    d2,d0
  201.     moveml    sp@+,d2-d7    | should really cause trap ?!? (mjr: why?)
  202.     rts
  203.  
  204. #endif __M68881__
  205.  
  206. __infinitydf:            | +infinity as proposed by IEEE
  207.     .long    0x7ff00000,0x00000000
  208.